﻿using System;
using Jay.Sc2.Bof.Lib.State;

namespace Jay.Sc2.Bof.Lib.Action.Terran
{
	public abstract class ActionSwitchAddOn : ActionProduceTerran
	{

		protected ActionSwitchAddOn() : base(3, 0, 0, 0) { }

		public override int AvailableProducer(IBuildOrder bo)
		{
			return Math.Min(GetInputBuilding(bo).Available, GetBuildingWithAddOn(bo).Available);
		}

		public override bool IsInvalid(IBuildOrder bo)
		{
			return base.IsInvalid(bo) || GetInputBuilding(bo).Total == 0 || GetBuildingWithAddOn(bo).Total == 0;
		}

		public override bool HaveTechnology(IBuildOrder bo)
		{
			return GetInputBuilding(bo).Total > 0 && GetBuildingWithAddOn(bo).Total > 0;
		}

		public override void Execute(IBuildOrder bo)
		{
			TerranState.TerranProductionBuilding building = GetInputBuilding(bo);
			TerranState.TerranProductionBuilding withAddOn = GetBuildingWithAddOn(bo);
			TerranState state = bo.State as TerranState;
			if (building.Available > 0 && withAddOn.Available > 0)
			{
				base.Execute(bo);
				building.Count--;
				withAddOn.Count--;
				GetOutputBuilding(bo).Building++;
				GetBuildingWithoutAddOn(bo).Building++;
				bo.AddAction(state.Time + 3, new ActionGeneric(SwitchActionName, (ActionGeneric.ActionExecuteDelegate)delegate(IBuildOrder ibo)
				{
					TerranState.TerranProductionBuilding ibuilding = GetOutputBuilding(ibo);
					TerranState.TerranProductionBuilding iwithoutAddOn = GetBuildingWithoutAddOn(ibo);
					ibuilding.Count++;
					ibuilding.Building--;
					iwithoutAddOn.Count++;
					iwithoutAddOn.Building--;
				}));
			}
			else throw new InvalidActionException();
		}

		public abstract TerranState.TerranProductionBuilding GetOutputBuilding(IBuildOrder bo);
		public abstract TerranState.TerranProductionBuilding GetInputBuilding(IBuildOrder bo);
		public abstract TerranState.TerranProductionBuilding GetBuildingWithAddOn(IBuildOrder bo);
		public abstract TerranState.TerranProductionBuilding GetBuildingWithoutAddOn(IBuildOrder bo);
		public abstract string SwitchActionName { get; }

	}
	public abstract class ActionProduceAddOn : ActionProduceTerran
	{

		protected ActionProduceAddOn(int buildTime, int minerals, int gas) : base(buildTime, minerals, gas, 0) { }

		public override int AvailableProducer(IBuildOrder bo)
		{
			return GetInputBuilding(bo).AvailableForProduction;
		}

		public override bool IsInvalid(IBuildOrder bo)
		{
			return base.IsInvalid(bo) || GetInputBuilding(bo).Total == 0;
		}

		public override bool HaveTechnology(IBuildOrder bo)
		{
			return GetInputBuilding(bo).Total > 0;
		}

		public override void Execute(IBuildOrder bo)
		{
			TerranState.TerranProductionBuilding building = GetInputBuilding(bo);
			TerranState state = bo.State as TerranState;
			if (building.AvailableForProduction > 0)
			{
				base.Execute(bo);
				building.Count--;
				GetOutputBuilding(bo).Building++;
				bo.AddAction(state.Time + BuildTime, new ActionGeneric(SpawnActionName, (ActionGeneric.ActionExecuteDelegate)delegate(IBuildOrder ibo)
				{
					TerranState.TerranProductionBuilding ibuilding = GetOutputBuilding(ibo);
					ibuilding.Building--;
					ibuilding.Count++;
				}));
			}
			else throw new InvalidActionException();
		}


		public abstract TerranState.TerranProductionBuilding GetOutputBuilding(IBuildOrder bo);
		public abstract TerranState.TerranProductionBuilding GetInputBuilding(IBuildOrder bo);
		public abstract string SpawnActionName { get; }

	}
	public abstract class ActionProduceTechLab : ActionProduceAddOn
	{
		public ActionProduceTechLab() : base(25, 50, 25) { }
	}
	public abstract class ActionProducReactor : ActionProduceAddOn
	{
		public ActionProducReactor() : base(50, 50, 50) { }
	}
	// ProduceTechLab
	public class ActionProduceTechLabOnBarracks : ActionProduceTechLab
	{
		public static ActionProduceTechLabOnBarracks Instance = new ActionProduceTechLabOnBarracks();

		private ActionProduceTechLabOnBarracks() { }

		public override string SpawnActionName { get { return "ActionSpawnTechLabOnBarracks"; } }

		public override TerranState.TerranProductionBuilding GetInputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Barracks;
		}

		public override TerranState.TerranProductionBuilding GetOutputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.BarracksTechLab;
		}

		private IAction[,] m_Requirements;
		public override IAction[,] Requirements
		{
			get
			{
				if (m_Requirements == null)
					m_Requirements = new IAction[,] { { ActionProduceBarracks.Instance, ActionProduceRefinery.Instance } };
				return m_Requirements;
			}
		}
	}
	public class ActionProduceTechLabOnFactory : ActionProduceTechLab
	{
		public static ActionProduceTechLabOnFactory Instance = new ActionProduceTechLabOnFactory();

		private ActionProduceTechLabOnFactory() { }

		public override string SpawnActionName { get { return "ActionSpawnTechLabOnFactory"; } }

		public override TerranState.TerranProductionBuilding GetInputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Factory;
		}

		public override TerranState.TerranProductionBuilding GetOutputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.FactoryTechLab;
		}

		private IAction[,] m_Requirements;
		public override IAction[,] Requirements
		{
			get
			{
				if (m_Requirements == null)
					m_Requirements = new IAction[,] { { ActionProduceFactory.Instance } };
				return m_Requirements;
			}
		}
	}
	public class ActionProduceTechLabOnStarport : ActionProduceTechLab
	{
		public static ActionProduceTechLabOnStarport Instance = new ActionProduceTechLabOnStarport();

		private ActionProduceTechLabOnStarport() { }

		public override string SpawnActionName { get { return "ActionSpawnTechLabOnStarport"; } }

		public override TerranState.TerranProductionBuilding GetInputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Starport;
		}

		public override TerranState.TerranProductionBuilding GetOutputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.StarportTechLab;
		}

		private IAction[,] m_Requirements;
		public override IAction[,] Requirements
		{
			get
			{
				if (m_Requirements == null)
					m_Requirements = new IAction[,] { { ActionProduceStarport.Instance } };
				return m_Requirements;
			}
		}
	}
	// ProduceReactor
	public class ActionProduceReactorOnBarracks : ActionProducReactor
	{
		public static ActionProduceReactorOnBarracks Instance = new ActionProduceReactorOnBarracks();

		private ActionProduceReactorOnBarracks() { }

		public override string SpawnActionName { get { return "ActionSpawnReactorOnBarracks"; } }

		public override TerranState.TerranProductionBuilding GetInputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Barracks;
		}

		public override TerranState.TerranProductionBuilding GetOutputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.BarracksReactor;
		}

		private IAction[,] m_Requirements;
		public override IAction[,] Requirements
		{
			get
			{
				if (m_Requirements == null)
					m_Requirements = new IAction[,] { { ActionProduceBarracks.Instance, ActionProduceRefinery.Instance } };
				return m_Requirements;
			}
		}
	}
	public class ActionProduceReactorOnFactory : ActionProducReactor
	{
		public static ActionProduceReactorOnFactory Instance = new ActionProduceReactorOnFactory();

		private ActionProduceReactorOnFactory() { }

		public override string SpawnActionName { get { return "ActionSpawnReactorOnFactory"; } }

		public override TerranState.TerranProductionBuilding GetInputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Factory;
		}

		public override TerranState.TerranProductionBuilding GetOutputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.FactoryReactor;
		}

		private IAction[,] m_Requirements;
		public override IAction[,] Requirements
		{
			get
			{
				if (m_Requirements == null)
					m_Requirements = new IAction[,] { { ActionProduceFactory.Instance } };
				return m_Requirements;
			}
		}
	}
	public class ActionProduceReactorOnStarport : ActionProducReactor
	{
		public static ActionProduceReactorOnStarport Instance = new ActionProduceReactorOnStarport();

		private ActionProduceReactorOnStarport() { }

		public override string SpawnActionName { get { return "ActionSpawnReactorOnStarport"; } }

		public override TerranState.TerranProductionBuilding GetInputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Starport;
		}

		public override TerranState.TerranProductionBuilding GetOutputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.StarportReactor;
		}

		private IAction[,] m_Requirements;
		public override IAction[,] Requirements
		{
			get
			{
				if (m_Requirements == null)
					m_Requirements = new IAction[,] { { ActionProduceStarport.Instance } };
				return m_Requirements;
			}
		}
	}
	//SwitchReactor
	public class ActionSwitchReactorFromBarracksToFactory : ActionSwitchAddOn
	{
		public static ActionSwitchReactorFromBarracksToFactory Instance = new ActionSwitchReactorFromBarracksToFactory();

		private ActionSwitchReactorFromBarracksToFactory() { }

		private IAction[,] m_Requirements;
		public override IAction[,] Requirements
		{
			get
			{
				if (m_Requirements == null)
				{
					m_Requirements = new IAction[,] { 
						{ ActionProduceFactory.Instance, ActionProduceReactorOnBarracks.Instance }, 
						{ ActionProduceFactory.Instance, ActionSwitchReactorFromStarportToBarracks.Instance }, 
					};
				}
				return m_Requirements;
			}
		}

		public override TerranState.TerranProductionBuilding GetOutputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.FactoryReactor;
		}

		public override TerranState.TerranProductionBuilding GetInputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Factory;
		}

		public override TerranState.TerranProductionBuilding GetBuildingWithAddOn(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.BarracksReactor;
		}

		public override TerranState.TerranProductionBuilding GetBuildingWithoutAddOn(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Barracks;
		}

		public override string SwitchActionName
		{
			get { return "ActionSwitchedReactorFromBarracksToFactory"; }
		}
	}
	public class ActionSwitchReactorFromBarracksToStarport : ActionSwitchAddOn
	{
		public static ActionSwitchReactorFromBarracksToStarport Instance = new ActionSwitchReactorFromBarracksToStarport();

		private ActionSwitchReactorFromBarracksToStarport() { }

		private IAction[,] m_Requirements;
		public override IAction[,] Requirements
		{
			get
			{
				if (m_Requirements == null)
				{
					m_Requirements = new IAction[,] { 
						{ ActionProduceStarport.Instance, ActionProduceReactorOnBarracks.Instance }, 
						{ ActionProduceStarport.Instance, ActionSwitchReactorFromFactoryToBarracks.Instance }, 
					};
				}
				return m_Requirements;
			}
		}

		public override TerranState.TerranProductionBuilding GetOutputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.StarportReactor;
		}

		public override TerranState.TerranProductionBuilding GetInputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Starport;
		}

		public override TerranState.TerranProductionBuilding GetBuildingWithAddOn(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.BarracksReactor;
		}

		public override TerranState.TerranProductionBuilding GetBuildingWithoutAddOn(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Barracks;
		}

		public override string SwitchActionName
		{
			get { return "ActionSwitchedReactorFromBarracksToStarport"; }
		}
	}
	public class ActionSwitchReactorFromFactoryToBarracks : ActionSwitchAddOn
	{
		public static ActionSwitchReactorFromFactoryToBarracks Instance = new ActionSwitchReactorFromFactoryToBarracks();

		private ActionSwitchReactorFromFactoryToBarracks() { }

		private IAction[,] m_Requirements;
		public override IAction[,] Requirements
		{
			get
			{
				if (m_Requirements == null)
				{
					m_Requirements = new IAction[,] { 
						{ ActionProduceFactory.Instance, ActionProduceReactorOnFactory.Instance }, 
						{ ActionProduceFactory.Instance, ActionSwitchReactorFromStarportToFactory.Instance }, 
					};
				}
				return m_Requirements;
			}
		}

		public override TerranState.TerranProductionBuilding GetOutputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.BarracksReactor;
		}

		public override TerranState.TerranProductionBuilding GetInputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Barracks;
		}

		public override TerranState.TerranProductionBuilding GetBuildingWithAddOn(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.FactoryReactor;
		}

		public override TerranState.TerranProductionBuilding GetBuildingWithoutAddOn(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Factory;
		}

		public override string SwitchActionName
		{
			get { return "ActionSwitchedReactorFromFactoryToBarracks"; }
		}
	}
	public class ActionSwitchReactorFromFactoryToStarport : ActionSwitchAddOn
	{
		public static ActionSwitchReactorFromFactoryToStarport Instance = new ActionSwitchReactorFromFactoryToStarport();

		private ActionSwitchReactorFromFactoryToStarport() { }

		private IAction[,] m_Requirements;
		public override IAction[,] Requirements
		{
			get
			{
				if (m_Requirements == null)
				{
					m_Requirements = new IAction[,] { 
						{ ActionProduceStarport.Instance, ActionProduceReactorOnFactory.Instance }, 
						{ ActionProduceStarport.Instance, ActionSwitchReactorFromBarracksToStarport.Instance }, 
					};
				}
				return m_Requirements;
			}
		}

		public override TerranState.TerranProductionBuilding GetOutputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.StarportReactor;
		}

		public override TerranState.TerranProductionBuilding GetInputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Starport;
		}

		public override TerranState.TerranProductionBuilding GetBuildingWithAddOn(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.FactoryReactor;
		}

		public override TerranState.TerranProductionBuilding GetBuildingWithoutAddOn(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Factory;
		}

		public override string SwitchActionName
		{
			get { return "ActionSwitchedReactorFromFactoryToStarport"; }
		}
	}
	public class ActionSwitchReactorFromStarportToBarracks : ActionSwitchAddOn
	{
		public static ActionSwitchReactorFromStarportToBarracks Instance = new ActionSwitchReactorFromStarportToBarracks();

		private ActionSwitchReactorFromStarportToBarracks() { }

		private IAction[,] m_Requirements;
		public override IAction[,] Requirements
		{
			get
			{
				if (m_Requirements == null)
				{
					m_Requirements = new IAction[,] { 
						{ ActionProduceReactorOnStarport.Instance }, 
						{ ActionSwitchReactorFromFactoryToStarport.Instance }, 
					};
				}
				return m_Requirements;
			}
		}

		public override TerranState.TerranProductionBuilding GetOutputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.BarracksReactor;
		}

		public override TerranState.TerranProductionBuilding GetInputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Barracks;
		}

		public override TerranState.TerranProductionBuilding GetBuildingWithAddOn(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.StarportReactor;
		}

		public override TerranState.TerranProductionBuilding GetBuildingWithoutAddOn(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Starport;
		}

		public override string SwitchActionName
		{
			get { return "ActionSwitchedReactorFromStarportToBarracks"; }
		}
	}
	public class ActionSwitchReactorFromStarportToFactory : ActionSwitchAddOn
	{
		public static ActionSwitchReactorFromStarportToFactory Instance = new ActionSwitchReactorFromStarportToFactory();

		private ActionSwitchReactorFromStarportToFactory() { }

		private IAction[,] m_Requirements;
		public override IAction[,] Requirements
		{
			get
			{
				if (m_Requirements == null)
				{
					m_Requirements = new IAction[,] { 
						{ ActionProduceReactorOnStarport.Instance }, 
						{ ActionSwitchReactorFromBarracksToStarport.Instance }, 
					};
				}
				return m_Requirements;
			}
		}

		public override TerranState.TerranProductionBuilding GetOutputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.FactoryReactor;
		}

		public override TerranState.TerranProductionBuilding GetInputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Factory;
		}

		public override TerranState.TerranProductionBuilding GetBuildingWithAddOn(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.StarportReactor;
		}

		public override TerranState.TerranProductionBuilding GetBuildingWithoutAddOn(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Starport;
		}

		public override string SwitchActionName
		{
			get { return "ActionSwitchedReactorFromStarportToFactory"; }
		}
	}
	//SwitchTechLab
	public class ActionSwitchTechLabFromBarracksToFactory : ActionSwitchAddOn
	{
		public static ActionSwitchTechLabFromBarracksToFactory Instance = new ActionSwitchTechLabFromBarracksToFactory();

		private ActionSwitchTechLabFromBarracksToFactory() { }

		private IAction[,] m_Requirements;
		public override IAction[,] Requirements
		{
			get
			{
				if (m_Requirements == null)
				{
					m_Requirements = new IAction[,] { 
						{ ActionProduceFactory.Instance, ActionProduceTechLabOnBarracks.Instance }, 
						{ ActionProduceFactory.Instance, ActionSwitchTechLabFromStarportToBarracks.Instance }, 
					};
				}
				return m_Requirements;
			}
		}

		public override TerranState.TerranProductionBuilding GetOutputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.FactoryTechLab;
		}

		public override TerranState.TerranProductionBuilding GetInputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Factory;
		}

		public override TerranState.TerranProductionBuilding GetBuildingWithAddOn(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.BarracksTechLab;
		}

		public override TerranState.TerranProductionBuilding GetBuildingWithoutAddOn(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Barracks;
		}

		public override string SwitchActionName
		{
			get { return "ActionSwitchedTechLabFromBarracksToFactory"; }
		}
	}
	public class ActionSwitchTechLabFromBarracksToStarport : ActionSwitchAddOn
	{
		public static ActionSwitchTechLabFromBarracksToStarport Instance = new ActionSwitchTechLabFromBarracksToStarport();

		private ActionSwitchTechLabFromBarracksToStarport() { }

		private IAction[,] m_Requirements;
		public override IAction[,] Requirements
		{
			get
			{
				if (m_Requirements == null)
				{
					m_Requirements = new IAction[,] { 
						{ ActionProduceTechLabOnBarracks.Instance, ActionProduceStarport.Instance }, 
						{ ActionSwitchTechLabFromFactoryToBarracks.Instance, ActionProduceStarport.Instance }, 
					};
				}
				return m_Requirements;
			}
		}

		public override TerranState.TerranProductionBuilding GetOutputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.StarportTechLab;
		}

		public override TerranState.TerranProductionBuilding GetInputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Starport;
		}

		public override TerranState.TerranProductionBuilding GetBuildingWithAddOn(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.BarracksTechLab;
		}

		public override TerranState.TerranProductionBuilding GetBuildingWithoutAddOn(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Barracks;
		}

		public override string SwitchActionName
		{
			get { return "ActionSwitchedTechLabFromBarracksToStarport"; }
		}
	}
	public class ActionSwitchTechLabFromFactoryToBarracks : ActionSwitchAddOn
	{
		public static ActionSwitchTechLabFromFactoryToBarracks Instance = new ActionSwitchTechLabFromFactoryToBarracks();

		private ActionSwitchTechLabFromFactoryToBarracks() { }

		private IAction[,] m_Requirements;
		public override IAction[,] Requirements
		{
			get
			{
				if (m_Requirements == null)
				{
					m_Requirements = new IAction[,] { 
						{ ActionProduceTechLabOnFactory.Instance }, 
						{ ActionSwitchTechLabFromStarportToFactory.Instance }, 
					};
				}
				return m_Requirements;
			}
		}

		public override TerranState.TerranProductionBuilding GetOutputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.BarracksTechLab;
		}

		public override TerranState.TerranProductionBuilding GetInputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Barracks;
		}

		public override TerranState.TerranProductionBuilding GetBuildingWithAddOn(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.FactoryTechLab;
		}

		public override TerranState.TerranProductionBuilding GetBuildingWithoutAddOn(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Factory;
		}

		public override string SwitchActionName
		{
			get { return "ActionSwitchedTechLabFromFactoryToBarracks"; }
		}
	}
	public class ActionSwitchTechLabFromFactoryToStarport : ActionSwitchAddOn
	{
		public static ActionSwitchTechLabFromFactoryToStarport Instance = new ActionSwitchTechLabFromFactoryToStarport();

		private ActionSwitchTechLabFromFactoryToStarport() { }

		private IAction[,] m_Requirements;
		public override IAction[,] Requirements
		{
			get
			{
				if (m_Requirements == null)
				{
					m_Requirements = new IAction[,] { 
						{ ActionProduceTechLabOnFactory.Instance, ActionProduceStarport.Instance }, 
						{ ActionSwitchTechLabFromBarracksToFactory.Instance, ActionProduceStarport.Instance }, 
					};
				}
				return m_Requirements;
			}
		}

		public override TerranState.TerranProductionBuilding GetOutputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.StarportTechLab;
		}

		public override TerranState.TerranProductionBuilding GetInputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Starport;
		}

		public override TerranState.TerranProductionBuilding GetBuildingWithAddOn(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.FactoryTechLab;
		}

		public override TerranState.TerranProductionBuilding GetBuildingWithoutAddOn(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Factory;
		}

		public override string SwitchActionName
		{
			get { return "ActionSwitchedTechLabFromFactoryToStarport"; }
		}
	}
	public class ActionSwitchTechLabFromStarportToBarracks : ActionSwitchAddOn
	{
		public static ActionSwitchTechLabFromStarportToBarracks Instance = new ActionSwitchTechLabFromStarportToBarracks();

		private ActionSwitchTechLabFromStarportToBarracks() { }

		private IAction[,] m_Requirements;
		public override IAction[,] Requirements
		{
			get
			{
				if (m_Requirements == null)
				{
					m_Requirements = new IAction[,] { 
						{ ActionProduceTechLabOnStarport.Instance }, 
						{ ActionSwitchTechLabFromFactoryToStarport.Instance }
					};
				}
				return m_Requirements;
			}
		}

		public override TerranState.TerranProductionBuilding GetOutputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.BarracksTechLab;
		}

		public override TerranState.TerranProductionBuilding GetInputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Barracks;
		}

		public override TerranState.TerranProductionBuilding GetBuildingWithAddOn(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.StarportTechLab;
		}

		public override TerranState.TerranProductionBuilding GetBuildingWithoutAddOn(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Starport;
		}

		public override string SwitchActionName
		{
			get { return "ActionSwitchedTechLabFromStarportToBarracks"; }
		}
	}
	public class ActionSwitchTechLabFromStarportToFactory : ActionSwitchAddOn
	{
		public static ActionSwitchTechLabFromStarportToFactory Instance = new ActionSwitchTechLabFromStarportToFactory();

		private ActionSwitchTechLabFromStarportToFactory() { }

		private IAction[,] m_Requirements;
		public override IAction[,] Requirements
		{
			get
			{
				if (m_Requirements == null)
				{
					m_Requirements = new IAction[,] { 
						{ ActionProduceTechLabOnStarport.Instance }, 
						{ ActionSwitchTechLabFromBarracksToStarport.Instance }, 
					};
				}
				return m_Requirements;
			}
		}

		public override TerranState.TerranProductionBuilding GetOutputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.FactoryTechLab;
		}

		public override TerranState.TerranProductionBuilding GetInputBuilding(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Factory;
		}

		public override TerranState.TerranProductionBuilding GetBuildingWithAddOn(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.StarportTechLab;
		}

		public override TerranState.TerranProductionBuilding GetBuildingWithoutAddOn(IBuildOrder bo)
		{
			TerranState state = bo.State as TerranState;
			return state.Starport;
		}

		public override string SwitchActionName
		{
			get { return "ActionSwitchedTechLabFromStarportToFactory"; }
		}
	}
}
